//package com.kelvem.saas.workbanch.core.experiment;
//
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.BeanDefinitionStoreException;
//import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
//import org.springframework.beans.factory.annotation.Lookup;
//import org.springframework.beans.factory.config.BeanDefinition;
//import org.springframework.context.ResourceLoaderAware;
//import org.springframework.context.annotation.Conditional;
//import org.springframework.context.annotation.ScannedGenericBeanDefinition;
//import org.springframework.core.env.Environment;
//import org.springframework.core.env.EnvironmentCapable;
//import org.springframework.core.io.Resource;
//import org.springframework.core.io.ResourceLoader;
//import org.springframework.core.io.support.ResourcePatternResolver;
//import org.springframework.core.io.support.ResourcePatternUtils;
//import org.springframework.core.type.AnnotationMetadata;
//import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
//import org.springframework.core.type.classreading.MetadataReader;
//import org.springframework.core.type.classreading.MetadataReaderFactory;
//import org.springframework.stereotype.Component;
//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Repository;
//import org.springframework.stereotype.Service;
//import org.springframework.util.Assert;
//import org.springframework.util.ClassUtils;
//
//import java.io.IOException;
//import java.util.LinkedHashSet;
//import java.util.Set;
//
//@Slf4j
//@Data
//@Service
///**
// * @see org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
// */
//public class ClassPathScanningCandidateComponentProviderSample implements EnvironmentCapable, ResourceLoaderAware {
//
//
//    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
//
//    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
//
//    private Environment environment;
//
//    private ResourcePatternResolver resourcePatternResolver;
//
//    private MetadataReaderFactory metadataReaderFactory;
//
//
//    /**
//     * Create a ClassPathScanningCandidateComponentProvider with the given {@link Environment}.
//     * {@link Component @Component}, {@link Repository @Repository},
//     * {@link Service @Service}, and {@link Controller @Controller}
//     * stereotype annotations
//     * @param environment the Environment to use
//     */
//    public ClassPathScanningCandidateComponentProviderSample(Environment environment) {
//        setEnvironment(environment);
//        setResourceLoader(null);
//    }
//
//
//    public Set<BeanDefinition> scanCandidateComponents(String basePackage) {
//        Set<BeanDefinition> candidates = new LinkedHashSet<>();
//        try {
//            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
//                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
//            boolean traceEnabled = log.isTraceEnabled();
//            boolean debugEnabled = log.isDebugEnabled();
//            for (Resource resource : resources) {
//                if (traceEnabled) {
//                    log.trace("Scanning " + resource);
//                }
//                if (resource.isReadable()) {
//                    try {
//                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//                        if (isCandidateComponent(metadataReader)) {
//                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
//                            sbd.setResource(resource);
//                            sbd.setSource(resource);
//                            if (isCandidateComponent(sbd)) {
//                                if (debugEnabled) {
//                                    log.debug("Identified candidate component class: " + resource);
//                                }
//                                candidates.add(sbd);
//                            }
//                            else {
//                                if (debugEnabled) {
//                                    log.debug("Ignored because not a concrete top-level class: " + resource);
//                                }
//                            }
//                        }
//                        else {
//                            if (traceEnabled) {
//                                log.trace("Ignored because not matching any filter: " + resource);
//                            }
//                        }
//                    }
//                    catch (Throwable ex) {
//                        throw new BeanDefinitionStoreException(
//                                "Failed to read candidate component class: " + resource, ex);
//                    }
//                }
//                else {
//                    if (traceEnabled) {
//                        log.trace("Ignored because not readable: " + resource);
//                    }
//                }
//            }
//        }
//        catch (IOException ex) {
//            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
//        }
//        return candidates;
//    }
//
//
//    /**
//     * Set the Environment to use when resolving placeholders and evaluating
//     * {@link Conditional @Conditional}-annotated component classes.
//     * @param environment the Environment to use
//     */
//    public void setEnvironment(Environment environment) {
//        Assert.notNull(environment, "Environment must not be null");
//        this.environment = environment;
//    }
//
//    @Override
//    public final Environment getEnvironment() {
//        return this.environment;
//    }
//
//    /**
//     * Set the {@link ResourceLoader} to use for resource locations.
//     * This will typically be a {@link ResourcePatternResolver} implementation.
//     * <p>Default is a {@code PathMatchingResourcePatternResolver}, also capable of
//     * resource pattern resolving through the {@code ResourcePatternResolver} interface.
//     * @see org.springframework.core.io.support.ResourcePatternResolver
//     * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
//     */
//    @Override
//    public void setResourceLoader(ResourceLoader resourceLoader) {
//        this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
//        this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
//    }
//
//    /**
//     * Return the ResourceLoader that this component provider uses.
//     */
//    public final ResourceLoader getResourceLoader() {
//        return this.resourcePatternResolver;
//    }
//
//    /**
//     * Set the {@link MetadataReaderFactory} to use.
//     * <p>Default is a {@link CachingMetadataReaderFactory} for the specified
//     * {@linkplain #setResourceLoader resource loader}.
//     * <p>Call this setter method <i>after</i> {@link #setResourceLoader} in order
//     * for the given MetadataReaderFactory to override the default factory.
//     */
//    public void setMetadataReaderFactory(MetadataReaderFactory metadataReaderFactory) {
//        this.metadataReaderFactory = metadataReaderFactory;
//    }
//
//    /**
//     * Return the MetadataReaderFactory used by this component provider.
//     */
//    public final MetadataReaderFactory getMetadataReaderFactory() {
//        return this.metadataReaderFactory;
//    }
//
//    /**
//     * Resolve the specified base package into a pattern specification for
//     * the package search path.
//     * <p>The default implementation resolves placeholders against system properties,
//     * and converts a "."-based package path to a "/"-based resource path.
//     * @param basePackage the base package as specified by the user
//     * @return the pattern specification to be used for package searching
//     */
//    protected String resolveBasePackage(String basePackage) {
//        return ClassUtils.convertClassNameToResourcePath(this.environment.resolveRequiredPlaceholders(basePackage));
//    }
//
//    /**
//     * Determine whether the given class does not match any exclude filter
//     * and does match at least one include filter.
//     * @param metadataReader the ASM ClassReader for the class
//     * @return whether the class qualifies as a candidate component
//     */
//    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
////        for (TypeFilter tf : this.excludeFilters) {
////            if (tf.match(metadataReader, this.metadataReaderFactory)) {
////                return false;
////            }
////        }
////        for (TypeFilter tf : this.includeFilters) {
////            if (tf.match(metadataReader, this.metadataReaderFactory)) {
////                return isConditionMatch(metadataReader);
////            }
////        }
//        return true;
//    }
//
//    /**
//     * Determine whether the given bean definition qualifies as candidate.
//     * <p>The default implementation checks whether the class is not an interface
//     * and not dependent on an enclosing class.
//     * <p>Can be overridden in subclasses.
//     * @param beanDefinition the bean definition to check
//     * @return whether the bean definition qualifies as a candidate component
//     */
//    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
//        AnnotationMetadata metadata = beanDefinition.getMetadata();
//        return (metadata.isIndependent() && (metadata.isConcrete() ||
//                (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
//    }
//}
